#include "solver.h"

solvergui::solvergui() : QObject(), dx_(0), dr_(0), mit_(0), 
    edited_(false), solutionConv_(0), solutionBif_(0), countConv_(0), countBif_(0)
{
    bifS.minX = 0.0; 
    bifS.maxX = 4.5; 
    bifS.numXTicks = 20; 
    bifS.minY = 0.0; 
    bifS.maxY = 1.1; 
    bifS.numYTicks = 5;
    convS.minX = 0.0; 
    convS.maxX = 10.0; 
    convS.numXTicks = 10; 
    convS.minY = 0.0; 
    convS.maxY = 1.1; 
    convS.numYTicks = 5; 
}

void solvergui::change_dr(const QString & dr)
{
    dr_ = dr.toDouble();
    edited_ = true;
}

void solvergui::change_itcount(const QString & it)
{
    mit_ = it.toInt();
    edited_ = true;
}

void solvergui::change_dx(const QString & dx)
{
    dx_ = dx.toDouble();
    edited_ = true;
}

void solvergui::solve()
{
    if (edited_)
    {
        if (mode_)
        {
            unsigned long long ncount = (unsigned long long) ((maxr - minr) / dr_ * (maxx - minx) / dx_);
            std::pair<double, double> * nsol = new std::pair<double, double>[ncount];
            unsigned long long i = 0;
            for (double cr = minr; cr < maxr && i < ncount; cr += dr_)
            {
                for (double cx = minx; cx < maxx && i < ncount; cx += dx_)
                {
                    double curx, prevx = cx;
                    for (int j = 0; j < mit_ && prevx > -3 && prevx < 5; ++j)
                    {
                        curx = cr * prevx * (1 - prevx);
                        prevx = curx;
                    }
                    if (curx > -0.4 && curx < 1.6)
                    {
                        nsol[i].first = cr;
                        nsol[i].second = curx;
                        ++i;
                    }
                }
            }
            if (solutionBif_ != 0)
                delete[] solutionBif_;
            solutionBif_ = nsol;
            countBif_ = i;
            edited_ = false;
        }
        else
        {
            unsigned long long ncount = mit_ + 1;
            std::pair<double, double> * nsol = new std::pair<double, double>[ncount];
            double curx, prevx = dx_;
            nsol[0].first = 0;
            nsol[0].second = dx_;
            int i = 1;
            for (int j = 1; j < ncount && prevx > -10 && prevx < 50; ++j)
            {
                curx = dr_ * prevx * (1 - prevx);
                prevx = curx;
                if (curx > -5 && curx < 5)
                    {
                        nsol[i].first = j;
                        nsol[i].second = curx;
                        ++i;
                    }
            }
            if (solutionConv_ != 0)
            {
                delete[] solutionConv_;
            }
            countConv_ = i;
            solutionConv_ = nsol;
            convS.maxX = mit_;
            convS.numXTicks = mit_;
            emit(drawerSet(convS));
        }
    }
    if (mode_)
        emit(solved(solutionBif_, countBif_, mode_));
    else
        emit(solved(solutionConv_, countConv_, mode_));
}

void solvergui::change_mode(bool m)
{
    mode_ = m;
    solve();
    if (mode_)
    {
        emit(drawerSet(bifS));
    }
    else
    {
        emit(drawerSet(convS));
    }
}

solvergui::~solvergui()
{
    if (solutionBif_ != 0)
        delete solutionBif_;
    if (solutionConv_ != 0)
        delete solutionConv_;
}